package models

import (
	"bigdevops/src/common"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"log"
)

// 工作流 审批流
type JobResult struct {
	Model // 不用每次写ID 和 createAt了

	// 需要创建一个 jobId和 hostIp的联和 唯一索引：一个任务给一个机器下发的结果只能有1条
	JobId    uint   `json:"jobId" gorm:"uniqueIndex:jid_hostip;"`
	Status   string `json:"status"  gorm:"comment:当前状态"`
	Stdout   string `json:"stdout"  gorm:"comment:标准输出"`
	Stderr   string `json:"stderr"  gorm:"comment:标准错误"`
	HostIp   string `json:"hostIp"  gorm:"type:varchar(100);uniqueIndex:jid_hostip;comment:ip"`
	HostName string `json:"hostName"  gorm:"comment:主机名"`
	Key      string `json:"key" gorm:"-"` //给前端表格
}

func (obj *JobResult) Create() error {
	return Db.Create(obj).Error

}
func (obj *JobResult) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func DeleteJobResultOneByInstanceId(iid string) error {

	return Db.Select(clause.Associations).Unscoped().Where("instance_id = ?", iid).Delete(&JobResult{}).Error
}

func (obj *JobResult) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *JobResult) UpdateOne() error {
	return Db.Where("id = ?", obj.ID).Updates(obj).Error

}

// 根据1个机器的状态 结合 错误策略 去更新这个任务的状态
// 如果只更新任务的状态 表，那么得等到下一轮才会真正的暂停之类的
// 因为多个agent的grpc 上报时间不一样的
// 下发的核心 是不是在cache map，我们只要让这个cache map 立即更新一次 就可以

func (obj *JobResult) JudgeByOnErrorStrategy() error {
	// 首先要拿到任务meta

	dbJobTask, err := GetJobTaskById(int(obj.JobId))
	log.Printf("JudgeByOnErrorStrategy: 错误:%v dbJobTask:%v,单机状态:%+v ", err, dbJobTask, obj)

	if err != nil {
		return err
	}
	// 如何判断任务是有问题的 stderr！=""
	switch obj.Status {
	// 成功的和 运行中的 跳过
	case common.AGENT_TASK_STATUS_SUCCESS, common.AGENT_TASK_STATUS_RUNNING:
		return nil
	}

	log.Printf("JudgeByOnErrorStrategy: 单个任务的状态：%v 任务id:%v  任务错误策略:%v 任务状态:%v ",
		obj.Status,
		dbJobTask.ID,
		dbJobTask.OnErrorStrategy,
		dbJobTask.Status,
	)
	switch dbJobTask.OnErrorStrategy {
	case common.JOB_ONERROR_STRATEGY_IGNORE:
		return nil

	case common.JOB_ONERROR_STRATEGY_PAUSE:
		// 更新这个任务的状态
		// kill动作无需更新状态
		if dbJobTask.Action == common.AGENT_TASK_ACTION_KILL {
			return nil
		}
		dbJobTask.Status = common.JOB_STATUS_PAUSED
		return dbJobTask.UpdateOne()

	case common.JOB_ONERROR_STRATEGY_STOP:
		dbJobTask.Status = common.JOB_STATUS_FINISHED
		return dbJobTask.UpdateOne()
	}
	return nil

}

func (obj *JobResult) GetOrCreate() error {

	var dbObj JobResult
	Db.Where("job_id = ? and host_ip = ? ", obj.JobId, obj.HostIp).Find(&dbObj)
	if dbObj.ID != 0 {
		return nil
	}
	return Db.Debug().Create(obj).Error

}

func GetJobResultCount() int {
	var count int64
	Db.Table("JobResultes").Count(&count)
	return int(count)
}

func GetJobResultAllWithLimitOffset(limit, offset int) (objs []*JobResult, err error) {
	err = Db.Preload("FlowNodes").Limit(limit).Offset(offset).Find(&objs).Error
	return
}

func GetJobResultsByJobId(jobId int) (objs []*JobResult, err error) {
	err = Db.Where("job_id = ? ", jobId).Find(&objs).Error
	return
}
func GetJobResultByJobIdAndHostIp(jobId int, hostIp string) (objs *JobResult, err error) {
	err = Db.Where("job_id = ? and host_ip = ? ", jobId, hostIp).First(&objs).Error
	return
}

// select * from ecs where
func GetJobResultByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*JobResult, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

func GetJobExecResultByJobId(jobId int) (objs []*JobResult, err error) {

	err = Db.Where("job_id = ?", jobId).Find(&objs).Error
	return

}
func GetJobExecResultDoneByJobId(jobId int) int {
	var count int64
	Db.Table("job_results").Where("status !='running' and job_id = ?", jobId).Count(&count)
	return int(count)

}

func GetJobResultByInstanceId(instanceId string) (*JobResult, error) {

	var dbObj JobResult
	err := Db.Where("instance_id = ?", instanceId).Preload("FlowNodes").First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("JobResult不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}

func GetJobResultById(id int) (*JobResult, error) {

	var dbObj JobResult
	err := Db.Where("id = ?", id).Preload("FlowNodes").First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("JobResult不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
